#ifndef ETAT_PARTIE_H
#   define ETAT_PARTIE_H


#include "carte_zone.h"
#include "def_statistiques.h"
#include "inventaire.h"



/**
 * \struct region_dans_zones_terminees etat_partie.h
 * Structure permettant de stocker les zones deja
 * terminees par le joueur dans une region donnee.\n
 * C'est un tableau dynamique de taille evolutive.
 */
struct region_dans_zones_terminees
{
    unsigned int id_region;
    unsigned char* tab;
    unsigned char nb_elem;
    unsigned char taille;
};



/**
 * \struct zones_terminees etat_partie.h
 * Structure permettant de stocker les zones deja terminees par le joueur.\n
 * C'est un tableau dynamique de taille evolutive.
 */
struct zones_terminees
{
    struct region_dans_zones_terminees* tab;
    unsigned int nb_elem;
    unsigned int taille;
};



/**
 * \struct regions_terminees etat_partie.h
 * Structure permettant de stocker les identifiants
 * des regions que le joueur a termine.
 */
struct regions_terminees
{
    struct tab_dyn_id regions;
    unsigned int taille;
};



/**
 * \struct etat_partie etat_partie.h
 *
 * Structure permettant de connaitre l'etat de la partie
 */
struct etat_partie
{
    char nom[32];
    unsigned int experience;
    unsigned int argent;

    /* statistiques */
    /**
     * Notez que les points de vie dans ces stats sont les points de vie
     * maximums du joueur. Pour obtenir ses points de vie actuels lors d'une
     * bataille, il faut consulter l'etat_bataille.\n
     * De plus, ces statistiques ne prennent pas en compte les bonus conferes
     * par l'equipement.
     */
    struct stats statistiques;

    /* localisation */
    unsigned int region;
    unsigned char zone;

    /* equipement */
    unsigned int arme;
    /**
     * un champ d'equipement vaut VIDE si il est vide
     * rappel : le champ arme ne peut etre vide
     */
    int veste;
    int gants;
    int chaussures;
    int accessoire;
    /**
     * pour un emplacement vide dans les objets utilisables,
     * utiliser la constante VIDE
     */
    int objets_utilisables[3];

    /* progression */
    struct zones_terminees terminees;
    struct regions_terminees reussies;
    struct inventaire objets_possedes;
};




/**
 * \fn struct etat_partie* creer_partie(void)
 * \brief Alloue de la memoire pour un etat partie et en renvoie l'adresse
 *
 * \return L'adresse du bloc alloue
 */
struct etat_partie* creer_partie(void);



/**
 * \fn void init_partie(struct etat_partie* partie)
 * \brief Remplit les champs d'un etat_partie avec les valeurs d'une nouvelle
 * partie (0 points d'experience, equipement de base...)
 *
 * \param[out] partie L'adresse de la partie a initialiser
 */
void init_partie(struct etat_partie* partie);



/**
 * \fn void detruire_partie(struct etat_partie* partie)
 * \brief libere la memoire allouee pour un etat_partie
 *
 * \param[in] partie L'adresse de la partie a detruire
 */
void detruire_partie(struct etat_partie* partie);



/**
 * \fn void init_zones_terminees(struct zones_terminees* zones, const unsigned int n)
 * \brief Initialise une structure zones_terminees en lui donnant une
 *        certaine capacite.
 *
 * \param[out] zones Un pointeur vers la structure concernee
 * \param[in] n La taille que l'on veut donner a la structure
 *
 * La taille d'une structure zones_terminees correspond au nombre de zones qui
 * pourront y etre enregistrees en temps constant. Pour les ajouts ulterieurs,
 * il faudra augmenter cette taille et recopier
 * toutes les valeurs dans un nouveau tableau.\n
 * En resume, lors du chargement d'une partie, on initialise la structure en
 * lui donnant une taille egale au nombre de zones que le joueur a terminees,
 * puis, si ce dernier termine une autre zone durant sa partie, il faudra
 * proceder a l'agrandissement.
 */
void init_zones_terminees(struct zones_terminees* zones, const unsigned int n);



/**
 * \fn void marquer_zone_terminee(struct zones_terminees* zones,
                                  const unsigned int id_region, const unsigned int id_zone)
 * \brief Ajoute une zone terminee a une liste de zones terminees
 *
 * \param[in,out] zones Un pointeur vers la liste a modifier
 * \param[in] id_region L'id de la region contenant la zone terminee
 * \param[in] id_zone L'id de la zone terminee
 */
void marquer_zone_terminee(struct zones_terminees* zones,
                           const unsigned int id_region, const unsigned int id_zone);



/**
 * \fn void detruire_zones_terminees(struct zones_terminees* zones)
 * \brief Libere la memoire allouee pour une structure zones_terminees
 *
 * \param[in,out] zones Un pointeur vers la liste a detruire
 */
void detruire_zones_terminees(struct zones_terminees* zones);



/**
 * \fn void init_regions_terminees(struct regions_terminees* regions, const unsigned int n)
 * \brief Initialise la liste des regions que le joueur a terminees
 *
 * \param[out] regions L'adresse du tableau de regions a initialiser
 * \param[in] n Le nombre de cases que le tableau aura lors de sa creation
 *
 * Note : le nombre de cases sera augmente en cas de besoin, mais par soucis
 * d'optimisation, mieux vaut donner un nombre adapte lors de l'initialisation.
 */
void init_regions_terminees(struct regions_terminees* regions, const unsigned int n);



/**
 * \fn void marquer_region_terminee(struct regions_terminees* regions, const unsigned int id_region)
 * \brief Ajoute un id de region a une liste de regions terminees
 *
 * \param[in,out] regions L'adresse du tableau de regions a modifier
 * \param[in] id_region L'id a ajouter au tableau
 */
void marquer_region_terminee(struct regions_terminees* regions, const unsigned int id_region);



/**
 * \fn char voir_si_zone_est_terminee(const struct etat_partie* partie,
                                      const unsigned int id_region,
                                      const unsigned int id_zone)
 * \brief Permet de savoir si une zone a deja ete terminee ou non
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \param[in] id_region Le numero de la region contenant la zone concernee
 * \param[in] id_zone Le numero de la zone concernee
 * \return VRAI si la zone a deja ete terminee, FAUX sinon
 */
char voir_si_zone_est_terminee(const struct etat_partie* partie,
                               const unsigned int id_region,
                               const unsigned int id_zone);



/**
 * \fn void detruire_regions_terminees(struct regions_terminees* regions)
 * \brief Libere la memoire allouee pour la liste des regions terminees
 *
 * \param[in] regions L'adresse du tableau de regions a detruire
 */
void detruire_regions_terminees(struct regions_terminees* regions);



/**
 * \fn unsigned int get_region_partie(const struct etat_partie* partie)
 * \brief Permet de savoir dans quelle region se trouve le joueur
 *
 * \param[in] partie L'adresse de l'etat de la partie
 */
unsigned int get_region_partie(const struct etat_partie* partie);



/**
 * \fn unsigned char get_zone_partie(const struct etat_partie* partie)
 * \brief Permet de savoir dans quelle zone se trouve le joueur
 *
 * \param[in] partie L'adresse de l'etat de la partie
 */
unsigned char get_zone_partie(const struct etat_partie* partie);



/**
 * \fn unsigned int get_quantite_possedee(const struct etat_partie* partie,
                                          const unsigned int id_objet)
 * \brief permet de savoir combien d'exemplaires d'un objet donne sont possedes par le joueur
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \param[in] id_objet L'id de l'objet auquel on s'interesse
 * \return Un entier de 0 a 999 inclus : la quantite possedee.
 *
 * \warning Ne pas appeler cette fonction avec id_objet = VIDE
 */
unsigned int get_quantite_possedee(const struct etat_partie* partie,
                                   const unsigned int id_objet);



/**
 * \fn char voir_si_region_accessible(const struct etat_partie* partie,
                                      const unsigned int id_region,
                                      const struct base_donnees* donnees)
 * \brief Dit si le joueur a acces a une region ou non
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \param[in] id_region Le numero de la region concernee
 * \param[in] donnees L'adresse d'une base de donnees correctement remplie
 * \return VRAI si la region est accessible, FAUX sinon
 */
char voir_si_region_accessible(const struct etat_partie* partie,
                               const unsigned int id_region,
                               const struct base_donnees* donnees);



/**
 * \fn char voir_si_region_terminee(const struct etat_partie* partie,
                                      const unsigned int id_region)
 * \brief Dit si le joueur a termine une region donnee ou non
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \param[in] id_region Le numero de la region concernee
 * \return VRAI si la region est terminee, FAUX sinon
 *
 * Rappel : une region est terminee si et seulement si le joueur a deja
 * remporte la bataille qui se trouve dans la "zone de boss" de cette region.
 */
char voir_si_region_terminee(const struct etat_partie* partie,
                             const unsigned int id_region);


/* ============ accesseurs pour les statistiques permanentes =============== */

/**
 * \fn unsigned int get_pv_max_perm(const struct etat_partie* partie)
 * \brief Obtient les pv max permanents du joueur (sans compter l'equipement)
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \return Les pv max "naturels" du joueur (entier positif)
 */
unsigned int get_pv_max_perm(const struct etat_partie* partie);



/**
 * \fn unsigned int get_puissance_perm(const struct etat_partie* partie);
 * \brief Obtient la puissance du joueur due a ses
 *        capacites propres (sans compter l'equipement)
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \return La puissance "naturelle" du joueur (entier positif)
 */
unsigned int get_puissance_perm(const struct etat_partie* partie);



/**
 * \fn unsigned int get_vitesse_deplacement_perm(const struct etat_partie* partie);
 * \brief Obtient la vitesse de deplacement du joueur due a ses
 *        capacites propres (sans compter l'equipement)
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \return La vitesse de deplacement "naturelle" du joueur (entier positif)
 */
unsigned int get_vitesse_deplacement_perm(const struct etat_partie* partie);



/**
 * \fn unsigned int get_vitesse_charge_perm(const struct etat_partie* partie);
 * \brief Obtient la vitesse de charge du joueur due a ses
 *        capacites propres (sans compter l'equipement)
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \return La vitesse de charge "naturelle" du joueur (entier positif)
 */
unsigned int get_vitesse_charge_perm(const struct etat_partie* partie);



/* ============ accesseurs pour l'equipement =============== */

/**
 * \fn int get_equipement(const struct etat_partie* partie,
                          const char champ)
 * \brief Permet de savoir quel objet est equipe a un emplacement donne
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \param[in] champ Le champ auquel on s'interesse :
 *                  ARME, VESTE, GANT, CHAUSSURE,
 *                  ACCESSOIRE, UTIL_1, UTIL_2, ou UTIL_3
 * \return VIDE si l'emplacement concernee est vide,
 *         l'id de l'objet equipe sinon
 */
int get_equipement(const struct etat_partie* partie,
                   const char champ);


#endif /* ETAT_PARTIE_H */
